//
//  CalendarMonthTiles.m
//  BBT
//
//  Created by JoyWang on 14-7-11.
//  Copyright (c) 2014年 tiewang. All rights reserved.
//

#import "CalendarMonthTiles.h"
#import "NSDate+TKCategory.h"
#import "NSDate+CalendarGrid.h"
#import "CalendarMonthView.h"
#import "TKGlobal.h"
static NSNumberFormatter *numberFormatter = nil;
@interface CalendarMonthTiles (){
    NSInteger firstOfPrev,lastOfPrev, today;
	NSInteger selectedDay,selectedPortion;
	NSInteger firstWeekday, daysInMonth;
	BOOL markWasOnToday,startOnSunday;
}
@property (nonatomic,assign) id target;
@property (nonatomic,assign) SEL action;

@property (nonatomic,strong) NSMutableArray *accessibleElements;

@property (nonatomic,strong) UIImageView *selectedImageView;
@property (nonatomic,strong) UILabel *currentDay;
@property (nonatomic,strong) UILabel *dot;
@property (nonatomic,strong) NSArray *datesArray;
@property (nonatomic,strong) NSTimeZone *timeZone;
@property (nonatomic,strong) NSArray *marks;

@end

@implementation CalendarMonthTiles
#pragma mark Init & Friends
- (instancetype) initWithMonth:(NSDate*)date marks:(NSArray*)markArray startDayOnSunday:(BOOL)sunday timeZone:(NSTimeZone*)timeZone{
    if(!(self=[super initWithFrame:CGRectZero])) return nil;
    self.backgroundColor = [UIColor whiteColor];
    numberFormatter =[[NSNumberFormatter alloc] init];
    self.timeZone = timeZone;
    
    firstOfPrev = -1;
    self.marks = markArray;
    _monthDate = date;
    startOnSunday = sunday;
    
    NSDateComponents *dateInfo = [_monthDate dateComponentsWithTimeZone:self.timeZone];
    firstWeekday = dateInfo.weekday;
    
    NSDate *prev = [_monthDate previousMonthWithTimeZone:self.timeZone];
    daysInMonth = [[_monthDate nextMonthWithTimeZone:self.timeZone] daysBetweenDate:_monthDate];
    
    NSArray *dates = [CalendarMonthTiles rangeOfDatesInMonthGrid:date startOnSunday:YES timeZone:self.timeZone];
    self.datesArray = dates;
    NSUInteger numberOfDaysBetween = [dates[0] daysBetweenDate:dates[1]];
    NSUInteger scale = (numberOfDaysBetween / 7) +1;
    CGFloat h = 30.0f *scale;
    NSDateComponents *todayInfo = [[NSDate date] dateComponentsWithTimeZone:self.timeZone];
	today = dateInfo.month == todayInfo.month && dateInfo.year == todayInfo.year ? todayInfo.day : -5;
	
	NSInteger preDayCnt = [prev daysBetweenDate:_monthDate];
	if(firstWeekday>1 && sunday){
		firstOfPrev = preDayCnt - firstWeekday+2;
		lastOfPrev = preDayCnt;
	}else if(!sunday && firstWeekday != 2){
		
		if(firstWeekday ==1){
			firstOfPrev = preDayCnt - 5;
		}else{
			firstOfPrev = preDayCnt - firstWeekday+3;
		}
		lastOfPrev = preDayCnt;
	}
    self.frame = CGRectMake(0, 1.0, VIEW_WIDTH, h+1);
	
	[self.selectedImageView addSubview:self.currentDay];
	[self.selectedImageView addSubview:self.dot];
	self.multipleTouchEnabled = NO;

    
    return self;
}
- (CGRect) rectForCellAtIndex:(NSInteger)index{
	
	NSInteger row = index / 7;
	NSInteger col = index % 7;
	
	return CGRectMake(col*VIEW_WIDTH/7-1, row*30+6, VIEW_WIDTH/7, 30);
}
- (void) drawTileInRect:(CGRect)r day:(NSInteger)day mark:(BOOL)mark font:(UIFont*)f1 font2:(UIFont*)f2 context:(CGContextRef)context color:(UIColor *)color{
    
    NSString *str = [numberFormatter stringFromNumber:@(day)];
	r.size.height -= 2;
	
	CGContextSetPatternPhase(context, CGSizeMake(r.origin.x, r.origin.y - 2));
    
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.alignment = NSTextAlignmentCenter;
    paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping;
	[str drawInRect:r withAttributes:@{ NSFontAttributeName:f1,NSParagraphStyleAttributeName:paragraphStyle,NSForegroundColorAttributeName:color}];
	
	if(mark){
		r.size.height = 10;
		r.origin.y += 19;
		[@"•" drawInRect:r withAttributes:@{ NSFontAttributeName:f1,NSParagraphStyleAttributeName:paragraphStyle,NSForegroundColorAttributeName:color}];
	}
	
    
    
}

- (void) drawRect:(CGRect)rect {
	
	CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetInterpolationQuality(context, kCGInterpolationNone);
    CGRect r = CGRectMake(-1, 0, VIEW_WIDTH/7, 30);
    UIFont *font = [UIFont systemFontOfSize:DATE_FONT_SIZE];
    UIFont *font2 =[UIFont systemFontOfSize:DOT_FONT_SIZE];
    UIFont *todayFont = [UIFont boldSystemFontOfSize:DATE_FONT_SIZE];
	NSInteger index = 0, mc = self.marks.count;
    UIColor *color = [UIColor blackColor];
    if(today > 0){
		NSInteger pre = firstOfPrev > 0 ? lastOfPrev - firstOfPrev + 1 : 0;
		NSInteger index = today +  pre-1;
		CGRect r = [self rectForCellAtIndex:index];
        BOOL mark = mc > 0 && index < mc ? [self.marks[index] boolValue] : NO;
        [self drawTileInRect:r day:today mark:mark font:todayFont font2:font2 context:context color:color];
    }
    color = [UIColor grayColor];
    if(firstOfPrev>0){
//		[color set];
		for(NSInteger i = firstOfPrev;i<= lastOfPrev;i++){
			r = [self rectForCellAtIndex:index];
			
			BOOL mark = mc > 0 && index < mc ? [self.marks[index] boolValue] : NO;
			[self drawTileInRect:r day:i mark:mark font:font font2:font2 context:context color:color];
            
			index++;
		}
	}
    color = [UIColor blackColor];
//	[color set];
	for(NSInteger i=1; i <= daysInMonth; i++){
		
		r = [self rectForCellAtIndex:index];
		
		BOOL mark = mc > 0 && index < mc ? [self.marks[index] boolValue] : NO;
		[self drawTileInRect:r day:i mark:mark font:font font2:font2 context:context color:color];
		index++;
	}
    color = [UIColor grayColor];
    NSInteger i = 1;
	while(index % 7 != 0){
		r = [self rectForCellAtIndex:index];
		BOOL mark = mc > 0 && index < mc ? [self.marks[index] boolValue] : NO;
		[self drawTileInRect:r day:i mark:mark font:font font2:font2 context:context color:color];
		i++;
		index++;
	}

	
}

+ (NSArray*) rangeOfDatesInMonthGrid:(NSDate*)date startOnSunday:(BOOL)sunday timeZone:(NSTimeZone*)timeZone{
    NSDate *firstDate, *lastDate;
	
	NSDateComponents *info = [date dateComponentsWithTimeZone:timeZone];
	
	info.day = 1;
	info.hour = info.minute = info.second = 0;
	
	NSDate *currentMonth = [NSDate dateWithDateComponents:info];
	info = [currentMonth dateComponentsWithTimeZone:timeZone];
	
	
	NSDate *previousMonth = [currentMonth previousMonthWithTimeZone:timeZone];
	NSDate *nextMonth = [currentMonth nextMonthWithTimeZone:timeZone];
	
	if(info.weekday > 1 && sunday){
		
		NSDateComponents *info2 = [previousMonth dateComponentsWithTimeZone:timeZone];
		
		NSInteger preDayCnt = [previousMonth daysBetweenDate:currentMonth];
		info2.day = preDayCnt - info.weekday + 2;
		firstDate = [NSDate dateWithDateComponents:info2];
		
		
	}else if(!sunday && info.weekday != 2){
		
		NSDateComponents *info2 = [previousMonth dateComponentsWithTimeZone:timeZone];
		NSInteger preDayCnt = [previousMonth daysBetweenDate:currentMonth];
		if(info.weekday==1){
			info2.day = preDayCnt - 5;
		}else{
			info2.day = preDayCnt - info.weekday + 3;
		}
		firstDate = [NSDate dateWithDateComponents:info2];
		
		
		
	}else{
		firstDate = currentMonth;
	}
	
	
	
	NSInteger daysInMonth = [currentMonth daysBetweenDate:nextMonth];
	info.day = daysInMonth;
	NSDate *lastInMonth = [NSDate dateWithDateComponents:info];
	NSDateComponents *lastDateInfo = [lastInMonth dateComponentsWithTimeZone:timeZone];
    
	
	
	if(lastDateInfo.weekday < 7 && sunday){
		
		lastDateInfo.day = 7 - lastDateInfo.weekday;
		lastDateInfo.month++;
		lastDateInfo.weekday = 0;
		if(lastDateInfo.month>12){
			lastDateInfo.month = 1;
			lastDateInfo.year++;
		}
		lastDate = [NSDate dateWithDateComponents:lastDateInfo];
        
	}else if(!sunday && lastDateInfo.weekday != 1){
		
		
		lastDateInfo.day = 8 - lastDateInfo.weekday;
		lastDateInfo.month++;
		if(lastDateInfo.month>12){ lastDateInfo.month = 1; lastDateInfo.year++; }
        
		
		lastDate = [NSDate dateWithDateComponents:lastDateInfo];
        
	}else{
		lastDate = lastInMonth;
	}
	
	
	
	return @[firstDate,lastDate];

}

- (void) setTarget:(id)t action:(SEL)a{
	self.target = t;
	self.action = a;
}

- (BOOL) selectDay:(NSInteger)day{
	NSInteger pre = firstOfPrev < 0 ?  0 : lastOfPrev - firstOfPrev + 1;
	
	NSInteger tot = day + pre;
	NSInteger row = tot / 7;
	NSInteger column = (tot % 7)-1;
	
	selectedDay = day;
	selectedPortion = 1;
	self.currentDay.font = [UIFont systemFontOfSize:DATE_FONT_SIZE];
    
	
	BOOL hasDot = NO;
	
	if(day == today){
//		self.currentDay.shadowOffset = CGSizeMake(0, -1);
		self.dot.shadowOffset = CGSizeMake(0, -1);
//		self.selectedImageView.image = [UIImage imageWithContentsOfFile:TKBUNDLE(@"calendar/Month Calendar Today Selected Tile.png")];
		markWasOnToday = YES;
		
	}else if(markWasOnToday){
		self.dot.shadowOffset = CGSizeMake(0, -1);
//		self.currentDay.shadowOffset = CGSizeMake(0, -1);
//		NSString *path = TKBUNDLE(@"calendar/Month Calendar Date Tile Selected.png");
//		self.selectedImageView.image = [[UIImage imageWithContentsOfFile:path] stretchableImageWithLeftCapWidth:1 topCapHeight:0];
		markWasOnToday = NO;
	}
	
    
	self.currentDay.text = [numberFormatter stringFromNumber:@(day)];
	
	if (self.marks.count > 0) {
		
		if([self.marks[row * 7 + column] boolValue]){
			hasDot = YES;
			[self.selectedImageView addSubview:self.dot];
		}else
			[self.dot removeFromSuperview];
		
	}else [self.dot removeFromSuperview];
	
	if(column < 0){
		column = 6;
		row--;
	}
    self.selectedImageView.frame = CGRectMakeWithSize((column*(VIEW_WIDTH/7))-1, (row*30)-1, self.selectedImageView.frame.size);
	[self addSubview:self.selectedImageView];
	
	
	return hasDot;
	
}
- (NSDate*) dateSelected{
	if(selectedDay < 1 || selectedPortion != 1) return nil;
	
	NSDateComponents *info = [_monthDate dateComponentsWithTimeZone:self.timeZone];
	info.hour = 0;
	info.minute = 0;
	info.second = 0;
	info.day = selectedDay;
	NSDate *d = [NSDate dateWithDateComponents:info];
	
    
	
	return d;
	
}

#pragma mark Touches
- (void) reactToTouch:(UITouch*)touch down:(BOOL)down{
	
	CGPoint p = [touch locationInView:self];
	/*
	 When a UIViewController allocated and pushViewController it in delegate.- (void)calendarMonthView:(TKCalendarMonthView *)monthView didSelectDate:(NSDate *)date.
	 p.x is over self.bounds.size.width(a cause -- unknown).
	 And column becomes 7 or more.
	 It is if it is the 4th [ or more ] row, App will crash (e.g. select 2012/07/29).
	 So I added check range of p.x.
	 */
	
	
	if(p.x > CGRectGetWidth(self.bounds) || p.x < 0) return;
	if(p.y > CGRectGetHeight(self.bounds) || p.y < 0) return;
	
	NSInteger column = p.x / (VIEW_WIDTH/7), row = p.y / 30;
	NSInteger day = 1, portion = 0;
	
	if(row == (int) (CGRectGetHeight(self.bounds) / 30)) row --;
	
	NSInteger fir = firstWeekday - 1;
	if(!startOnSunday && fir == 0) fir = 7;
	if(!startOnSunday) fir--;
	
	
	if(row==0 && column < fir){
		day = firstOfPrev + column;
	}else{
		portion = 1;
		day = row * 7 + column  - firstWeekday+2;
		if(!startOnSunday) day++;
		if(!startOnSunday && fir==6) day -= 7;
        
	}
	if(portion > 0 && day > daysInMonth){
		portion = 2;
		day = day - daysInMonth;
	}
	
	self.currentDay.font = [UIFont systemFontOfSize:DATE_FONT_SIZE];
	self.currentDay.hidden = NO;
	self.dot.hidden = NO;
	
	if(portion != 1){
		markWasOnToday = YES;
		self.selectedImageView.image = nil;
		self.selectedImageView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.15];
		self.currentDay.hidden = YES;
		self.dot.hidden = YES;
		
	}else if(portion==1 && day == today){
//		self.currentDay.shadowOffset = CGSizeMake(0, -1);
		self.dot.shadowOffset = CGSizeMake(0, -1);
//		self.selectedImageView.image = [UIImage imageWithContentsOfFile:TKBUNDLE(@"calendar/Month Calendar Today Selected Tile.png")];
		markWasOnToday = YES;
	}else if(markWasOnToday){
		self.dot.shadowOffset = CGSizeMake(0, -1);
//		self.currentDay.shadowOffset = CGSizeMake(0, -1);
//		NSString *path = TKBUNDLE(@"calendar/Month Calendar Date Tile Selected.png");
//		self.selectedImageView.image = [[UIImage imageWithContentsOfFile:path] stretchableImageWithLeftCapWidth:1 topCapHeight:0];
		markWasOnToday = NO;
	}
	
	[self addSubview:self.selectedImageView];
	self.currentDay.text = [NSString stringWithFormat:@"%ld",(long)day];
	
	if (self.marks.count > 0) {
		if([self.marks[row * 7 + column] boolValue])
			[self.selectedImageView addSubview:self.dot];
		else
			[self.dot removeFromSuperview];
	}else{
		[self.dot removeFromSuperview];
	}
	
    
	
	
	self.selectedImageView.frame = CGRectMakeWithSize((column*(VIEW_WIDTH/7))-1, (row*30)-1, self.selectedImageView.frame.size);
	
	if(day == selectedDay && selectedPortion == portion) return;
	
	
	
	if(portion == 1){
		selectedDay = day;
		selectedPortion = portion;
		[self.target performSelector:self.action withObject:@[@(day)]];
		
	}else if(down){
		[self.target performSelector:self.action withObject:@[@(day),@(portion)]];
		selectedDay = day;
		selectedPortion = portion;
	}
	
}

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
	//[super touchesBegan:touches withEvent:event];
	[self reactToTouch:[touches anyObject] down:NO];
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
	[self reactToTouch:[touches anyObject] down:NO];
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
	[self reactToTouch:[touches anyObject] down:YES];
}

#pragma mark Properties

- (UILabel *)currentDay{
    if (_currentDay) {
        return _currentDay;
    }
    CGRect r = self.selectedImageView.bounds;
	r.origin.y -= 1;
	_currentDay = [[UILabel alloc] initWithFrame:r];
	_currentDay.text = @"1";
	_currentDay.textColor = [UIColor whiteColor];
	_currentDay.backgroundColor = [UIColor clearColor];
	_currentDay.font = [UIFont boldSystemFontOfSize:DATE_FONT_SIZE];
	_currentDay.textAlignment = NSTextAlignmentCenter;
	_currentDay.shadowColor = [UIColor darkGrayColor];
	_currentDay.shadowOffset = CGSizeMake(0, -1);
    return _currentDay;
}
- (UILabel *) dot{
	if(_dot) return _dot;
	
	CGRect r = self.selectedImageView.bounds;
	r.origin.y += 30;
	r.size.height -= 31;
	_dot = [[UILabel alloc] initWithFrame:r];
	_dot.text = @"•";
	_dot.textColor = [UIColor whiteColor];
	_dot.backgroundColor = [UIColor clearColor];
	_dot.font = [UIFont boldSystemFontOfSize:DOT_FONT_SIZE];
	_dot.textAlignment = NSTextAlignmentCenter;
	_dot.shadowColor = [UIColor darkGrayColor];
	_dot.shadowOffset = CGSizeMake(0, -1);
	return _dot;
}

- (UIImageView *) selectedImageView{
	if(_selectedImageView) return _selectedImageView;
	_selectedImageView = [[UIImageView alloc] init];
	_selectedImageView.layer.magnificationFilter = kCAFilterNearest;
	_selectedImageView.frame = CGRectMake(0, 0, VIEW_WIDTH/7, 30);
    [_selectedImageView setBackgroundColor:[UIColor colorWithRed:(CGFloat)1/255  green:(CGFloat)160/255 blue:(CGFloat)186/255 alpha:1.0]];
	return _selectedImageView;
}




@end
